<?php

namespace StudyBuddy\String;

/**
 * String tokenizer
 * Minics the behaviour
 * or java.unil.StringTokenizer class
 *
 * If you need to just get array
 * of tokens and not bother with
 * the nextToken() methods you can
 * just call getArrayCopy() on this object
 * and get array of tokens
 *
 */
class Tokenizer extends \ArrayObject {

    /**
     * By default the string will be split
     * buy one or more space or tab or new line char
     *
     * @var string Regex pattern
     */
    protected $delim = '/([,]+)/';
    protected $origString;
    protected $iterator;

    /**
     * @param string $string Original string to be tokenized
     * @param string $delim must be a valid PCRE pattern!
     * It's recommended to add the /u switch to pattern to treat
     * chars in pattern as UTF-8 chars
     */
    public function __construct($string, $delim = '/([,]+)/') {
        if (!is_string($string) || !is_string($delim)) {
            throw new \InvalidArgimentException('$string and $delim params must be string');
        }

        parent::__construct(array());
        $this->origString = $string;
        $this->delim = $delim;



        $this->exchangeArray($this->parse($string));
        $this->iterator = $this->getIterator();
    }

    public function getDelim() {
        return $this->delim;
    }

    public function getOrigString() {
        return $this->origString;
    }

    /**
     * Parse string into tokens
     * Sub-class may override this to
     * tokenize any other way.
     * For example, may also apply a filter
     * like array_unique or filter agains stopwords list
     *
     * @return array array of tokens (individual parts of string)
     */
    public function parse() {
        $a = \preg_split($this->delim, $this->origString, -1, PREG_SPLIT_NO_EMPTY);
        d('tokenized: ' . print_r($a, 1));

        return $a;
    }

    /**
     * Tests if there are more tokens available
     * from this tokenizer's string
     *
     * @return bool true if there are more tokens
     *
     */
    public function hasMoveTokens() {
        return $this->iterator->valid();
    }

    /**
     *
     * Returns the next token from this string tokenizer
     *
     * @return string
     */
    public function nextToken() {
        $s = $this->iterator->current();
        $this->iterator->next();

        return $s;
    }

    /**
     *
     * Calculates the number of times that this tokenizer's
     * nextToken method can be called
     * before it generates an exception.
     *
     * @return int number of tokens in the origString
     */
    public function countTokens() {
        return $this->count();
    }

}
